<?php
/*
 *
 *
 * TODO проанализировать micron~DbSimple/Generic
 *
 * [?] Что нужно делать в конструкторе
 * [?] Что происходит при вызове пустого конструктора $a = new SectionsModel();
 * [?] Стоит ли впихивать в this.data поле count
 *
 */
abstract class BDModel {

    protected $table;
    protected $db;
    protected $sql;

    private $column;
    private $value;
    private $data      = array();
    private $dataStart = array();

    public $offset = '';
    public $limit = '';
    public $order_by_column = '';
    public $order = '';

    public $search = '';
    public $searchField = '';
    public $searchOper = '';
    public $searchString = '';

    protected  $virtual_modul_index;

    /*
     * @param column:
     * @param value :
     * @param params: {offset|limit|order_by_column|order}
     */
    function __construct($column = null, $value = null, $params = null){

        $this->db = Registry::getInstance() -> get('db');

        $this->virtual_modul_index = Registry::getInstance()->virtual_modul_index ;

        $this->column = $column;
        $this->value = $value;

        #
        if(isset($params['offset'])) $this->offset = $params['offset'];
        if(isset($params['limit'])) $this->limit = $params['limit'];
        if(isset($params['order_by_column'])){
            $this->order_by_column = $params['order_by_column'];
            if( ($s = str_replace(':','',$params['order_by_column'])) != $this->order_by_column){
                $tmp = explode(':',$this->order_by_column);
                $this->order_by_column = $tmp[0] . "." . $tmp[1];
            }
        }
        if(isset($params['order'])) $this->order = $params['order'];

        $offset = '';
        $limit = '';
        $order_by_column = '';
        $order = '';

        if($this->offset != ''){
            $this->offset = (int)$this->offset - 1;
            $this->offset = (string)$this->offset;
            $offset = " OFFSET " . $this->offset;
        }
        if($this->limit != '')  $limit  = " LIMIT " . $this->limit;
        if($this->order_by_column != '')  $order_by_column  = " ORDER BY " . $this->order_by_column . "";
        if($this->order != '')  $order  =  $this->order;

        if($this->order_by_column != '') $this->order = '';

        #
        if( !is_null($column) AND !is_null($value) ){
        // вызов конструктора с парпметрами
            $sql = "SELECT * FROM `{$this->table}` WHERE `{$column}` = '{$value}' $order_by_column $order $limit $offset;";
            $this->data = $this->db->select($sql);
            $this->dataStart = $this->data;
        } else {
        // вызов без параметров вернет всю таблицу
            /*
            $sql = "SELECT * FROM `{$this->table}` LIMIT 1 OFFSET 0";
            $this->data = $this->db->select($sql);
            $this->dataStart = $this->data;
            */
        }
        ///fb($sql);
    }

    function Select(){
        $this->data = $this->db->select($this->sql);
    }

    function Go(){
        $data  = $this->db->select($this->sql);
        $this->data = $data;
        $this->dataStart = $data;
    }

    function Insert(){
        return $this->db->insert($this->sql);
    }

    function Sql($q){
        $this->sql = $q;
    }

    function getData(){
        return $this->data;
    }

    function setData($data){
        $this->data = $this->validate($data);
    }

    public function IsExists(){
    //TODO
        //return $this->db->selectCell("SELECT COUNT(*) FROM ?# WHERE ?# = ?d", $this->table, $this->column, $this->value) > 0;
    }

    public function HasChanges(){
    //TODO
        return $this->data != $this->dataStart;
    }

    /*
     * Добавить запись c валидацией
     */
    function Set($data, $update_id = null){

        $this->data = array();

        foreach($data as $key => $val){
            $this->$key  = $val;
        }

        $this->dataStart = $this->validate($this->data);

        return $this->Flush();

    }

    function validate($data){
        //TODO валидацию

        return $data;
    }

    function del(){

        $sql = "DELETE  FROM `{$this->table}` WHERE `{$this->column}` = '{$this->value}';";


        $res = $this->db->query($sql);


    }

    public function Delete(){
    //TODO

        /*
        $ret = false;
        if ($this->readOnly || $this->isDel)
        {
            return $ret;
        }

        if ($this->id)
        {
            $ret = $this->db->query("DELETE FROM ?# WHERE ?# = ?d",
                $this->table,
                $this->idField,
                $this->id);
        }
        $this->isDel = $ret;

        return $ret;
        */
    }

    /*
    public function Flush(){
    //TODO
    // [!] Если this->data не содержит this->data[count] и this->data[data]

        $ret = false;

        if (count($this->data)){
            if($this->value){
                if ($this->dataStart != $this->data){
                    $data = array();

                    foreach ($this->data as $k => $v){
                        if($k == $this->column) continue;
                        $data[$k] = $v;

                        $ret = $this->db->query("UPDATE `{$this->table}`
                                                SET
                                                    {$data}
                                                WHERE
                                                    `{$this->column}` = '{$this->value}';"
                        );

                    }
                }
                $ret = $this->value;
            } else {
                $ret = $this->db->query("INSERT INTO
                                                ?#(?#)
                                            VALUES
                                                (?a)",
                    $this->table,
                    array_keys($this->data),
                    array_values($this->data)
                );
                $this->value = $this->data[$this->column] = $ret;
            }
        }

        return $ret;
    }
*/

    /*
     * При вставке массив вида array()
     * При апдейте - array(0 => array(), 1 => array())
     */
    public function Flush(){
    //TODO вставить защиту от инъекций и doSecure

        $keys = array_keys($this->data);
        $vals =  array_values($this->data);

        if($this->data == $this->dataStart){

            $cols =  implode('`, `', $keys);
            $values = implode("', '", $vals);

            if($cols == "`0`" OR $values == 'Array') return false;

            $sql = "INSERT INTO `".$this->table."` (`$cols`) VALUES ('$values'); ";

            return $this->db->insert($sql);

        } else {
            foreach($this->data as $i => $row){
                $str_where = '';
                $str = '';

                $index = 1;
                foreach($row as $col_name => $value){
                    if($index == 1){
                        $str_where .= " `$col_name` = '$value' ";
                    } else {
                       $str .= " `$col_name` = '$value', ";

                    }
                    $index++;
                }

                $str = substr($str, 0, -2);

                $sql = "UPDATE `".$this->table."` SET $str WHERE $str_where ;";

                return $this->db->update($sql);
            }
        }

        return;

    }

    public function __set($key, $value)        {
    //TODO
        /*
            if ($this->isDel)
            {
                trigger_error("Can not change removed object!", E_USER_ERROR);
            }

            if ($this->readOnly)
            {
                trigger_error("Can not change readonly object!", E_USER_ERROR);
            }

            if ($key == $this->idField)
            {
                trigger_error("Can not change id field!", E_USER_ERROR);
            }
        */

            return $this->data[$key] = $value;
        }

    /*
    public function __get($key)        {
    //TODO
            // Нельзя получать данные из объекта который удалён
            if ($this->isDel)
            {
                trigger_error("Can not get value from removed object!", E_USER_ERROR);
            }

            // Если спрашивают ключевое поле, но сейчас идёт только заполнение данных то пытаетмся сделать запись в БД и вернуть id который она скажет
            if (in_array($key, array($this->idField, 'id')) && !$this->id && count($this->data))
            {
                return $this->Flush();
            }
            return $this->data[$key];
        }

    public function __destruct(){
    //TODO
        return $this->Flush();
    }
    */


    /*
     * Компилятор запросов
     * [!] Сейчас - в процессе развития
     */
    function constructQuery($options = array()){

        $query = '';

        $table = '';
        //$operation = '';

        $cols = '';
        $vals = '';

        if(isset($options['table'])){
            $table = $options['table'];
            //TODO validation $table
        }

        /*
        if(isset($options['operation'])){
            $operation = $options['operation'];
        }
        */

        if(isset($options['columns']) ){
            if(is_array($options['columns'])){
                for($i=0; $i<count($options['columns']); $i++){

                    if(isset($options['columns'][$i]['col_name']))  $col_name = $options['columns'][$i]['col_name'];
                    if(isset($options['columns'][$i]['value']))     $value = $options['columns'][$i]['value'];
                    if(isset($options['columns'][$i]['connector'])) $connector = $options['columns'][$i]['connector'];

                    //TODO validation
                    //$col_name, $value, $connector

                    $cols .=  $connector . " `{$col_name}` = '{$value}' " ;

                }
            }
        }

        $query .= "SELECT * FROM $table WHERE $cols";





        return $query;
    }
}